<?php
/**
 * Created by PhpStorm.
 * User: 554665488
 * Date: 2018-6-8
 * Time: 0:37
 * @description:
 * @Author: yfl
 * @QQ 554665488
 */

class magic
{
    protected $array = array();
    public $name = 'yfl';
    public $age;
    private $db = 'obj';
    private $balance;

    public function __construct($age = 25, $balance = 1000)
    {
        $this->age = $age . '年龄一个人的秘密不希望在对象被序列化的时候传输的时候被别人看到';

        $this->balance = $balance;
    }


    public function __set($name, $value)
    {
        $this->array[$name] = $value;
    }

    public function __get($name)
    {
        return $this->array[$name];
    }

    public function __call($name, $arguments)
    {
        var_dump($name, $arguments);
    }

    public static function __callStatic($name, $arguments)
    {
        var_dump($name, $arguments);
    }

    public function __toString()
    {
        return '对象被echo的时候自动调用';
    }

    public function __invoke($params)
    {
        echo "对象被作为函数调用的时候自动回调invoke.\n";
        var_dump($params);
    }

    //该方法会在类的对象被var_dump的时候被调用，如若没有定义该方法，这回var_dump()打印所有类的属性
    public function __debugInfo()
    {
        return ['db' => $this->db, 'age' => $this->age]; //必须返回一个数组
    }

    //在对象给序列化的时候被调用       也就是把一个类转换成了一个字符串，可以传输或者保存下来。
    public function __sleep()
    {
        $this->age = '年龄是一个人的秘密';
        return array('age', 'name'); //这是返回的必须是一个数据参数是类的属性
    }

    //zai
    public function __wakeup()
    {
        $this->age = '对象被反序列化的时候可以看到秘密';//如果存在__debugInfo魔术方法打印一个对象的时候先执行___debugInfo过滤对象的属性

        //对象被反序列化的时候就不用返回一个数组了就是对应的字符串的解密，字符串已经有了就不用其他的了
    }

    public function __destruct()
    {
        $test =new Test();  //在析构方法中可以创建一对象
            echo $test->a;
       //是否可以引入文件
        require_once __DIR__.'/class1.php';  //使用绝对路径或者使用相对路径都是可以的
        $class1= new class1();
        var_dump($class1);
    }

    public function __clone()
    {

        //生成一个新对象
        // TODO: Implement __clone() method.
    }

    public function __isset($name)
    {
        echo '想判断对象的属性'.$name.'是否可见的时候自动调用';
        //当 用isset() 判断对象不可见的属性时(protected/private/不存在的属性)
        //会引发 __isset()来执行

    }

    public function __unset($name)
    {
       //销毁一个对象属性的时候调用
        echo '销毁一个对象属性的时候调用'.$name;
    }
  //该方法的唯一参数是一个数组，其中包含array('property'=>value,...)格式排列的属性
    public static function __set_state($an_array)  //就是var_export()的回调函数 必须是一静态的方法
    {
        echo 'ar_export()一个对象的时候的回调函数'; //有人问这有什么用？是没多大用，最大的作用可以复制一个对象。只需改下代码而已
        // TODO: Implement __set_state() method.
    }


}

class Test
{
    public  $a='aaa';
    //该方法的唯一参数是一个数组，其中包含array('property'=>value,...)格式排列的属性
    public static function __set_state($an_array)  //就是var_export()的回调函数 必须是一静态的方法
    {
        echo 'ar_export()一个对象的时候的回调函数'; //有人问这有什么用？是没多大用，最大的作用可以复制一个对象。只需改下代码而已
        $tmp = new Test();
        $tmp->a = str_replace('$test','$b',$an_array['a']);//直接赋值
        return $tmp;//必须返回一个对象，可以是其他类的对象
    }

}
//有的人问，你为什么不用__clone进行回调呢？这正是我想说的地方，个人认为__clone()
// 没有 __set_state()强大，因为__clone()没有可以接受的参数，局限了“进化”的范围，我用个例子说明。  https://my.oschina.net/zhangdapeng89/blog/40296

//$obj = new magic();
//$obj->name='set';
////echo $obj->name;
//$obj->fun('params');
//magic::staticFun('static params');
//echo $obj;
//$obj('params');
//print_r(serialize($obj));
//print_r(unserialize(serialize($obj)));
//var_dump(isset($obj->asdsa));
//unset($obj->aaaaa);
$test =new Test();
$test->a = '我是$test';
var_export($test, true);
var_dump($test);